package com.bestv.engine.model;

import com.bestv.engine.filter.Filters;
import com.bestv.utils.common.Constants;
import net.sf.json.JSON;
import net.sf.json.xml.XMLSerializer;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * Created by Henry on 14-5-21.
 */
public class RecommendationRule implements Serializable {
    private Logger logger = LoggerFactory.getLogger(getClass());

    private List<RecommendationItem> recommendationItemList;
    private long requestId;
    private String method;
    private boolean canRuleBeFilled = false;
    private boolean needSelection = false;
    private int tag;
    private int maxSize;
    private String preference;

    public RecommendationRule() {
        recommendationItemList = new ArrayList<RecommendationItem>();
    }

    public void addAll(List<RecommendationItem> items) {
        addAll(items, Constants.ITEMS_PER_MODEL);
    }

    public void addAll(List<RecommendationItem> items, int size) {
        addAll(items, size, null);
    }

    public void addAll(List<RecommendationItem> items, int size, Filters filters) {
        int i = 0;
        for (RecommendationItem item : items) {
            if (filters != null && !filters.accept(item)) continue;
            recommendationItemList.add(item);
            i++;
            if (i >= size || isFull()) break;
        }
    }

    @Override
    public String toString() {
        StringBuilder sbString = new StringBuilder();
        for (RecommendationItem item : recommendationItemList) {
            sbString.append(item).append("\n");
        }
        return sbString.toString();
    }

    public String toXML() {
        StringBuilder sbXML = new StringBuilder();
        sbXML.append(String.format("<%s_get_response>", method));
        sbXML.append(String.format("<canrulebefilled>%s</canrulebefilled>", canRuleBeFilled));
        sbXML.append(String.format("<needselection>%s</needselection>", needSelection));
        sbXML.append("<recommendation>");
        sbXML.append("<recommenditems list=\"true\">");
        for (RecommendationItem item : recommendationItemList) {
            sbXML.append(item.toXML());
        }
        sbXML.append("</recommenditems>");
        if (StringUtils.isNotBlank(preference)) {
            sbXML.append(String.format("<preference><![CDATA[%s]]></preference>", preference));
        }
        sbXML.append(String.format("<programtype>%s</programtype>", tag));
        sbXML.append(String.format("<total_results>%s</total_results>", recommendationItemList.size()));
        sbXML.append("</recommendation>");
        sbXML.append(String.format("<recid>%s</recid>", requestId));
        sbXML.append(String.format("</%s_get_response>", method));
        return sbXML.toString();
    }

    public String toJSON() {
        XMLSerializer serializer = new XMLSerializer();
        JSON json = serializer.read(toXML());
        return json.toString(1);
    }

    public String toHTML() {
        StringBuilder sbHTML = new StringBuilder();
        sbHTML.append("<table>");
        sbHTML.append("<tr>");
        sbHTML.append(String.format("<th>%s</th>", "itemId"));
        sbHTML.append(String.format("<th>%s</th>", "biz"));
        sbHTML.append(String.format("<th>%s</th>", "category"));
        sbHTML.append(String.format("<th>%s</th>", "name"));
        sbHTML.append(String.format("<th>%s</th>", "isSeries"));
        sbHTML.append(String.format("<th>%s</th>", "typeId"));
        sbHTML.append(String.format("<th>%s</th>", "isCharge"));
        sbHTML.append(String.format("<th>%s</th>", "modelName"));
        sbHTML.append(String.format("<th>%s</th>", "score"));
        sbHTML.append("</tr>");
        for (RecommendationItem item : recommendationItemList) {
            sbHTML.append(item.toHTML());
        }
        sbHTML.append("</table>");
        return sbHTML.toString();
    }

    public String format(String fmt) {
        String converter = String.format("to%s", fmt.toUpperCase());
        if (!"toHTML".equals(converter) && !"toXML".equals(converter) && !"toJSON".equals(converter)) return null;

        String result = null;
        try {
            Method convert = getClass().getMethod(converter);
            result = (String) convert.invoke(this);
        } catch (NoSuchMethodException e) {
            logger.error("No such method.", e);
        } catch (InvocationTargetException e) {
            logger.error("Error on invocation target.", e);
        } catch (IllegalAccessException e) {
            logger.error("Error on illegal access.", e);
        }
        return result;
    }

    public int size() {
        return recommendationItemList.size();
    }

    public boolean isFull() {
        return size() >= getMaxSize();
    }

    public List<RecommendationItem> getRecommendationItemList() {
        return recommendationItemList;
    }

    public void setRequestId(long requestId) {
        this.requestId = requestId;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public void setCanRuleBeFilled(boolean canRuleBeFilled) {
        this.canRuleBeFilled = canRuleBeFilled;
    }

    public void setNeedSelection(boolean needSelection) {
        this.needSelection = needSelection;
    }

    public void setTag(int tag) {
        this.tag = tag;
    }

    public void setMaxSize(int maxSize) {
        this.maxSize = maxSize;
    }

    public int getMaxSize() {
        return maxSize == 0 ? Constants.ITEMS_PER_MODEL : maxSize;
    }

    public void setPreference(String preference) {
        this.preference = preference;
    }
}
